﻿#if !UNITY_2022_1_OR_NEWER
using UnityEngine;
using UnityEngine.AI;

namespace GameToolkit
{
    [ExecuteInEditMode]
    [DefaultExecutionOrder(-101)]
    [AddComponentMenu("Navigation/NavMeshLink", 33)]
    [HelpURL("https://github.com/Unity-Technologies/NavMeshComponents#documentation-draft")]
    public class NavMeshLinkRT : MonoBehaviour, ITransformSensor
    {
        [SerializeField]
        int m_AgentTypeID;
        public int agentTypeID { get { return m_AgentTypeID; } set { m_AgentTypeID = value; ResetLink(); } }

        [SerializeField]
        Vector3 m_StartPoint = new Vector3(0.0f, 0.0f, -2.5f);
        public Vector3 startPoint { get { return m_StartPoint; } set { m_StartPoint = value; ResetLink(); } }

        [SerializeField]
        Vector3 m_EndPoint = new Vector3(0.0f, 0.0f, 2.5f);
        public Vector3 endPoint { get { return m_EndPoint; } set { m_EndPoint = value; ResetLink(); } }

        [SerializeField]
        float m_Width;
        public float width { get { return m_Width; } set { m_Width = value; ResetLink(); } }

        [SerializeField]
        int m_CostModifier = 1;
        public int costModifier { get { return m_CostModifier; } set { m_CostModifier = value; ResetLink(); } }

        [SerializeField]
        bool m_Bidirectional = true;
        public bool bidirectional { get { return m_Bidirectional; } set { m_Bidirectional = value; ResetLink(); } }

        [SerializeField]
        bool m_AutoUpdatePosition;
        public bool autoUpdate { get { return m_AutoUpdatePosition; } set { SetAutoUpdate(value); } }

        [SerializeField]
        int m_Area;
        public int area
        {
            get { return m_Area; }
            set
            {
                if (m_Area != value)
                {
                    m_Area = value; 
                    ResetLink();
                }
            }
        }

        NavMeshLinkInstance m_LinkInstance;

        //Vector3 m_LastPosition = Vector3.zero;
        //Quaternion m_LastRotation = Quaternion.identity;
        TransformSensor.Sensor mSensor;

        void OnEnable()
        {
            AddLink();
            if (m_AutoUpdatePosition && m_LinkInstance.valid)
                mSensor = TransformSensor.CreateTransformSensor(transform, this);
        }

        void OnDisable()
        {
            if (mSensor != null)
                mSensor.Release();
            m_LinkInstance.Remove();
        }

        void ITransformSensor.OnTransformChanged(Transform trans, ETransformSensorFlag flags)
        {
            ResetLink();
        }

        public void ResetLink()
        {
            if (m_LinkInstance.valid)
            {
                m_LinkInstance.Remove();
                AddLink();
            }
        }
        void SetAutoUpdate(bool value)
        {
            if (m_AutoUpdatePosition == value)
                return;
            m_AutoUpdatePosition = value;
            var sen = mSensor;
            if (value && m_LinkInstance.valid)
                mSensor = TransformSensor.CreateTransformSensor(transform, this);
            else
                mSensor = null;
            if (sen != null)
                sen.Release();
        }

        void AddLink()
        {
#if UNITY_EDITOR
            if (m_LinkInstance.valid)
            {
                Debug.LogError("Link is already added: " + this);
                return;
            }
#endif

            var link = new NavMeshLinkData();
            link.startPosition = m_StartPoint;
            link.endPosition = m_EndPoint;
            link.width = m_Width;
            link.costModifier = m_CostModifier;
            link.bidirectional = m_Bidirectional;
            link.area = m_Area;
            link.agentTypeID = m_AgentTypeID;
            m_LinkInstance = NavMesh.AddLink(link, transform.position, transform.rotation);
            if (m_LinkInstance.valid)
                m_LinkInstance.owner = this;

            //m_LastPosition = transform.position;
            //m_LastRotation = transform.rotation;
        }

        //bool HasTransformChanged()
        //{
        //    if (m_LastPosition != transform.position) return true;
        //    if (m_LastRotation != transform.rotation) return true;
        //    return false;
        //}

        //void OnDidApplyAnimationProperties()
        //{
        //    UpdateLink();
        //}

        //static void UpdateTrackedInstances()
        //{
        //    foreach (var instance in s_Tracked)
        //    {
        //        if (instance.HasTransformChanged())
        //            instance.UpdateLink();
        //    }
        //}

#if UNITY_EDITOR
        void OnValidate()
        {
            m_Width = Mathf.Max(0.0f, m_Width);

            if (!m_LinkInstance.valid)
                return;

            ResetLink();
            var s = mSensor;
            if (m_AutoUpdatePosition)
                mSensor = TransformSensor.CreateTransformSensor(transform, this);
            else
                mSensor = null;
            if(s != null)
                s.Release();
            //UpdateLink();

            //if (!m_AutoUpdatePosition)
            //{
            //    RemoveTracking(this);
            //}
            //else if (!s_Tracked.Contains(this))
            //{
            //    AddTracking(this);
            //}
        }
#endif
    }
}

#endif